package tools.project.controller {
	import kiwi.util.ArrayUtils;
	import kiwi.util.reflect.ReflectHelper;
	import kiwi.util.reflect.TypeHelper;

	import tools.event.ProjectEvent;
	import tools.model.ActionFrameInfo;
	import tools.model.ActionInfo;
	import tools.model.EditorConfig;
	import tools.model.EmptyFrameInfo;
	import tools.model.FrameInfo;
	import tools.model.TileInfo;

	import org.robotlegs.mvcs.Command;

	import flash.events.Event;

	/**
	 * 加载项目
	 * @author zhangming.luo
	 */
	public class LoadProjectCommand extends Command {
		[Inject]
		public var config : EditorConfig;
		[Inject]
		public var event : ProjectEvent;
		private var xml : XML;

		override public function execute() : void {
			dispatch(new ProjectEvent(ProjectEvent.NEW));
			if (event.file.data == null) {
				event.file.addEventListener(Event.COMPLETE, onLoaded);
				event.file.load();
			} else {
				onLoaded(null);
			}
		}

		private function onLoaded(e : Event) : void {
			xml = new XML(event.file.data);
			config.projectDir = event.file.parent;
			config.projectName = event.file.name.toLowerCase().replace(".sprite", "");
			config.texture.file = event.file.parent.resolvePath(xml.texture).nativePath;
			config.texture.addEventListener(Event.COMPLETE, onComplete);
			config.texture.postConstruct();
		}

		private function onComplete(event : Event) : void {
			var tiles : Array = [];
			var frames : Array = [];
			var actions : Array = [];
			var item : XML;
			for each (item in xml.tiles.*) {
				var tile : TileInfo = new TileInfo();
				applyObjectByXML(tile, item);
				tile.$source = config.texture;
				tiles.push(tile);
			}
			for each (item in xml.frames.*) {
				var frame : FrameInfo = new FrameInfo();
				applyObjectByXML(frame, item);
				frame.tileList = ArrayUtils.transform(getArray(item.tileList.item, int), function(e : int) : TileInfo {
					return ArrayUtils.findFirst(tiles, "id", e);
				});
				frame.$source = config.texture;
				frames.push(frame);
			}
			for each (item in xml.actions.*) {
				var action : ActionInfo = new ActionInfo();
				applyObjectByXML(action, item);
				var frameId : Array = getArray(item.frame.item, int);
				var frameDuration : Array = getArray(item.frame_duration.item, int);
				for (var i : int = 0;i < frameId.length;i++) {
					var info : ActionFrameInfo = new ActionFrameInfo();
					if (frameId[i] == -1) {
						info.frame = new EmptyFrameInfo();
					} else {
						info.frame = ArrayUtils.findFirst(frames, "id", frameId[i]);
					}
					info.duration = frameDuration[i];
					action.frameList.push(info);
				}
				actions.push(action);
			}
			config.allFrameList = frames;
			config.allTileList = tiles;
			config.actionList = actions;
			dispatch(new ProjectEvent(ProjectEvent.TEXTURE_IMG_LOADED));
			dispatch(new ProjectEvent(ProjectEvent.LOAD_COMPLETE));
		}

		private function getArray(xml : XMLList, clz : Class) : Array {
			var result : Array = [];
			for each (var item:XML in xml) {
				var value : String = item.text();
				if (clz == String) {
					result.push(value);
				} else if (clz == int || clz == uint || clz == Number) {
					result.push(Number(value));
				} else if (clz == Boolean) {
					result.push(Boolean(value));
				} else {
					result.push(clz(value));
				}
			}
			return result;
		}

		private function applyObjectByXML(obj : *, xml : XML) : void {
			for each (var subXML:XML in xml.*) {
				var field : String = subXML.localName();
				if (!obj.hasOwnProperty(field)) {
					continue;
				}
				var type : Class = TypeHelper.getClass(TypeHelper.getFieldType(obj, field));
				if (type == Array) {
					// 不处理数组
					continue;
				} else if (type == String) {
					obj[field] = subXML.text();
				} else if (type == Number || type == int || type == uint) {
					obj[field] = Number(subXML.text());
				} else if (type == Boolean) {
					obj[field] = Boolean(subXML.text());
				} else {
					if (obj[field] == null) {
						obj[field] = ReflectHelper.newInstance(type);
					}
					applyObjectByXML(obj[field], subXML);
				}
			}
		}
	}
}
